package com.sinosoft.dsp.platform.action;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.RequestScoped;
import javax.faces.component.UIComponent;
import javax.faces.component.html.HtmlInputHidden;
import javax.faces.event.ActionEvent;

import org.primefaces.json.JSONException;
import org.primefaces.json.JSONObject;

import com.sinosoft.builder.templates.app.CommandType;
import com.sinosoft.builder.templates.app.MenuItem;
import com.sinosoft.builder.templates.app.Parameter;
import com.sinosoft.dsp.platform.components.system.ITabBean;
import com.sinosoft.dsp.platform.components.system.IWindowBean;
import com.sinosoft.dsp.platform.components.system.IWindowSetViewBean;
import com.sinosoft.dsp.platform.components.system.TabBean;
import com.sinosoft.dsp.platform.components.system.WindowBean;
import com.sinosoft.dsp.platform.exception.SinoPlatformException;
import com.sinosoft.dsp.platform.manager.ApplicationBuilder;
import com.sinosoft.dsp.platform.manager.ApplicationController;
import com.sinosoft.dsp.platform.services.PlatformNavigationService;
import com.sinosoft.dsp.platform.utils.FacesContextUtils;
import com.sinosoft.dsp.platform.utils.MessageBundles;
import com.sinosoft.dsp.system.core.exception.SinoXMLException;
import com.sinosoft.dsp.system.core.log.Log;
import com.sinosoft.dsp.system.to.IGenericTO;
import com.sinosoft.dsp.system.to.attribute.Attribute;
import com.sinosoft.dsp.system.to.exception.SinoAttributeException;
import com.sinosoft.dsp.system.to.helper.ToHelper;
import com.sinosoft.dsp.system.utils.Const;

/**
 * 平台通用页面行为类
 * 
 * @author 潘巍（Peter Pan）
 * @since 2011-4-6 下午09:26:56
 */
@ManagedBean(name = "portalAction")
@RequestScoped
public class PortalAction {

	private static final Log log = Log.getLog(PortalAction.class.getName());

	@ManagedProperty(value = "#{applicationController}")
	private ApplicationController applicationController;

	@ManagedProperty(value = "#{applicationBuilder}")
	private ApplicationBuilder applicationBuilder;

	@ManagedProperty(value = "#{platformNavigationService}")
	private PlatformNavigationService navi;

	@ManagedProperty(value = "#{windowSetViewBean}")
	private IWindowSetViewBean winset;

	@ManagedProperty(value = "#{messageBundles}")
	private MessageBundles messageBundles;

	/**
	 * 事件的Id
	 */
	private String eventId;

	/**
	 * 命令类型
	 */
	private CommandType commandType;

	/**
	 * 按钮的行为入口
	 * 
	 * @param actionEvent
	 */
	public void buttonAction(ActionEvent actionEvent) {
		try {
			String at = FacesContextUtils.getParameter("actionType");
			SingletonSceneType ss = SingletonSceneType.getScene(at);

			// 根据类型（actionType）调用相应的创建方法
			if (SingletonSceneType.TAB == ss) {
				addCallbackParamForTab(createTabByButton());
			} else if (SingletonSceneType.WINDOW == ss) {
				addCallbackParamForWin(popupWindowByButton());
			}

			FacesContextUtils.addCallbackParam("actionType", ss.getName());

		} catch (Exception e) {
			log.error("按钮行为调用入口出现错误(buttonAction):" + e.getMessage());
			FacesContextUtils.addGlobalErrorFacesMessage("添加标签出现错误！（错误信息："
					+ e.getMessage() + "）");
		}
	}

	/**
	 * 通过按钮创建Tab
	 * 
	 * @return
	 * @throws SinoAttributeException
	 * @throws SinoPlatformException
	 * @throws JSONException
	 */
	private ITabBean createTabByButton() throws SinoAttributeException,
			SinoPlatformException, JSONException {
		JSONObject jo = getButtonParamsJSONObject(FacesContextUtils
				.getParameter("params", null));
		IGenericTO gto = transformActionToGTOForButton(jo);
		gto.add(createParamAttribute("parentId", FacesContextUtils
				.getParameter("parentId", null)));

		return applicationController.createTab(jo.optString("displayName"), jo
				.optString("image16"), jo.has("closable") ? jo
				.optBoolean("closable") : true, FacesContextUtils
				.getParameter("sceneId"), FacesContextUtils
				.getParameter("layoutId"), gto);
	}

	/**
	 * 通过按钮创建Win
	 * 
	 * @return
	 * @throws SinoAttributeException
	 * @throws JSONException
	 * @throws SinoPlatformException
	 */
	private IWindowBean popupWindowByButton() throws SinoAttributeException,
			JSONException, SinoPlatformException {
		JSONObject jo = getButtonParamsJSONObject(FacesContextUtils
				.getParameter("params", null));
		IGenericTO gto = transformActionToGTOForButton(jo);
		gto.add(createParamAttribute("parentId", FacesContextUtils
				.getParameter("parentId", null)));
		Map<String, String> params = transformToMapForButton(jo);

		return applicationController.popupWindow(FacesContextUtils
				.getParameter("sceneId"), FacesContextUtils
				.getParameter("layoutId"), params, gto, FacesContextUtils
				.getParameter("parentId", null));
	}

	private JSONObject getButtonParamsJSONObject(String params)
			throws JSONException {
		if (Const.isEmpty(params)) {
			return new JSONObject();
		} else {
			return new JSONObject(params);
		}
	}

	private IGenericTO transformActionToGTOForButton(JSONObject jo)
			throws SinoAttributeException, JSONException {

		IGenericTO actionTo = ToHelper.createGenericTO();

		IGenericTO content = ToHelper.createGenericTO();
		if (jo != null) {
			String key;
			for (Iterator<?> iter = jo.keys(); iter.hasNext();) {
				key = (String) iter.next();
				content.add(createParamAttribute(key, jo.optString(key)));
			}
		}

		actionTo.addRelation(ToHelper.ATTRIBUTE_CONTENT, content);
		return actionTo;
	}

	private Map<String, String> transformToMapForButton(JSONObject jo) {
		Map<String, String> params = new HashMap<String, String>();
		if (jo != null) {
			String key;
			for (Iterator<?> iter = jo.keys(); iter.hasNext();) {
				key = (String) iter.next();
				params.put(key, jo.optString(key));
			}
		}
		return params;
	}

	public void refleshHomeModel(ActionEvent actionEvent) {
		UIComponent model = actionEvent.getComponent();
		String modelId = model.getId();
		modelId = modelId.substring(0, modelId.length() - 8);
		// TODO
		// IModuleBean mb = (IModuleBean) applicationController
		// .getViewBeanById(modelId);
		// mb.handleFlush();
	}

	/**
	 * 菜单的行为入口
	 * 
	 * @return
	 */
	public void naviMenuAction(ActionEvent actionEvent) {
		try {
			UIComponent menu = actionEvent.getComponent();
			HtmlInputHidden menuIdH = (HtmlInputHidden) menu.getChildren().get(
					0);
			// 通过EventId获得MenuItem
			this.eventId = (String) menuIdH.getValue();
			MenuItem m = navi.getMenuItemById(this.eventId);
			// 获得命令类型
			CommandType mc = m.getCmdid();
			if (mc == null) {
				throw new SinoPlatformException("无法获得菜单的行为命令！");
			}
			this.commandType = mc;
			// 获得行为的类型（Tab、Win）
			String at = mc.getActionType();
			SingletonSceneType ss = SingletonSceneType.getScene(at);

			// 根据类型（actionType）调用相应的创建方法
			if (SingletonSceneType.TAB == ss) {
				addCallbackParamForTab(createTab());
			} else if (SingletonSceneType.WINDOW == ss) {
				addCallbackParamForWin(popupWindow());
			}

			FacesContextUtils.addCallbackParam("actionType", ss.getName());

		} catch (SinoPlatformException e) {
			log.error("导航行为调用入口出现错误(naviMenuAction)");
			log.error(e.getMessage());
			FacesContextUtils.addGlobalErrorFacesMessage(e.getMessage());
		} catch (Exception e) {
			log.error("导航行为调用入口出现错误(naviMenuAction)");
			FacesContextUtils.addGlobalErrorFacesMessage("添加标签出现错误！");
		}
	}

	private void addCallbackParamForTab(ITabBean bean) throws SinoXMLException {
		if (!Const.isEmpty(bean.getId()))
			FacesContextUtils.addCallbackParam("tabId", bean.getId());

		FacesContextUtils.addCallbackParam("tabLable", messageBundles.getValue(
				bean.getAttr(TabBean.ATTRIBUTE_LABEL), bean
						.getAttr(TabBean.ATTRIBUTE_LABEL)));
		FacesContextUtils.addCallbackParam("tabClosable", bean
				.getAttr(TabBean.ATTRIBUTE_CLOSABLE));
		FacesContextUtils.addCallbackParam("tabImage16", bean
				.getAttr(TabBean.ATTRIBUTE_IMAGE16));

		String src = bean.getAttr(TabBean.ATTRIBUTE_SRC);
		if (!Const.isEmpty(src)) {
			FacesContextUtils.addCallbackParam("tabContentSrc", src);
		} else if (bean.getLayout() != null
				&& !Const.isEmpty(bean.getLayout().getSrc())) {
			src = bean.getLayout().getSrc();
			if (src.contains("?")) {
				src += "&";
			} else {
				src += "?";
			}
			src += "sceneId=" + bean.getScene().getId() + "&layoutId="
					+ bean.getLayout().getId();
			FacesContextUtils.addCallbackParam("tabContentSrc", src);
		}
	}

	private void addCallbackParamForWin(IWindowBean bean) {
		if (!Const.isEmpty(bean.getId()))
			FacesContextUtils.addCallbackParam("winId", bean.getId());
		FacesContextUtils.addCallbackParam("winContentId", bean.getContent()
				.getId());
		for (String attributeLabel : WindowBean.ATTRIBUTE) {
			if (!Const.isEmpty(bean.getAttrs().get(attributeLabel))) {
				FacesContextUtils.addCallbackParam(attributeLabel, bean
						.getAttrs().get(attributeLabel));
			}
		}
	}

	private ITabBean createTab() throws SinoAttributeException,
			SinoPlatformException {

		MenuItem m = navi.getMenuItemById(this.getEventId());

		Parameter tcs = navi.getParameterByCommandType(this.getCommandType(),
				"targetContentSceneId");
		Parameter tcl = navi.getParameterByCommandType(this.getCommandType(),
				"targetContentLayoutId");
		Parameter closable = navi.getParameterByCommandType(this
				.getCommandType(), "closable");
		Parameter image16 = navi.getParameterByCommandType(this
				.getCommandType(), "image16");
		Parameter displayName = navi.getParameterByCommandType(this
				.getCommandType(), "displayName");
		Parameter src = navi.getParameterByCommandType(this.getCommandType(),
				"src");

		String displayNameStr = null;
		if (displayName != null) {
			displayNameStr = displayName.getValue();
		} else {
			displayNameStr = m.getDisplayName();
		}

		Boolean closableStr = null;
		if (closable != null && !Const.isEmpty(closable.getValue())) {
			closableStr = Boolean.valueOf(closable.getValue());
		}

		String image16Str = null;
		if (image16 != null) {
			image16Str = image16.getValue();
		} else if (!Const.isEmpty(m.getImage16())) {
			image16Str = m.getImage16();
		}

		IGenericTO gto = transformActionToGTO();
		if (src != null) {
			return applicationController.createTabBySrc(displayNameStr,
					image16Str, closableStr, src.getValue(), gto);
		} else {
			return applicationController.createTab(displayNameStr, image16Str,
					closableStr, tcs.getValue(), tcl.getValue(), gto);
		}
	}

	private IWindowBean popupWindow() throws SinoAttributeException,
			SinoPlatformException {

		MenuItem m = navi.getMenuItemById(this.getEventId());

		Map<String, String> params = new HashMap<String, String>();

		Parameter tcs = navi.getParameterByCommandType(this.getCommandType(),
				"targetContentSceneId");
		Parameter tcl = navi.getParameterByCommandType(this.getCommandType(),
				"targetContentLayoutId");

		for (String attributeLabel : WindowBean.ATTRIBUTE) {
			addPopupWindowParamByCommand(params, attributeLabel);
		}

		if (Const.isEmpty(params.get(WindowBean.ATTRIBUTE_LABEL_DISPLAY_NAME))) {
			params.put(WindowBean.ATTRIBUTE_LABEL_DISPLAY_NAME, m
					.getDisplayName());
		}

		if (Const.isEmpty(params.get(WindowBean.ATTRIBUTE_LABEL_IMAGE16))) {
			params.put(WindowBean.ATTRIBUTE_LABEL_IMAGE16, m.getImage16());
		}

		IGenericTO gto = transformActionToGTO();
		return applicationController.popupWindow(tcs.getValue(),
				tcl.getValue(), params, gto, null);
	}

	private void addPopupWindowParamByCommand(Map<String, String> params,
			String paramName) {
		Parameter p = navi.getParameterByCommandType(this.getCommandType(),
				paramName);
		if (p != null) {
			params.put(paramName, p.getValue());
		}
	}

	/**
	 * 将Action的参数转换为GTO
	 * 
	 * @return
	 * @throws SinoAttributeException
	 */
	private IGenericTO transformActionToGTO() throws SinoAttributeException {
		IGenericTO actionTo = ToHelper.createGenericTO();
		actionTo.add(createParamAttribute("eventId", this.eventId));
		IGenericTO content = ToHelper.createGenericTO();
		List<Parameter> params = this.getCommandType().getParameter();
		if (params != null) {
			for (Parameter p : params) {
				if (!Const.isEmpty(p.getKey())) {
					content.add(createParamAttribute(p.getKey(), p.getValue()));
				}
			}
		}
		actionTo.addRelation(ToHelper.ATTRIBUTE_CONTENT, content);
		return actionTo;
	}

	private Attribute<?> createParamAttribute(String name, String value)
			throws SinoAttributeException {
		if (value == null) {
			return null;
		}
		Attribute<?> param = ToHelper.createToAttributeByValue(value);
		param.setName(name);
		param.setConcept(name);
		return param;
	}

	public String getEventId() {
		return eventId;
	}

	public void setEventId(String eventId) {
		this.eventId = eventId;
	}

	public CommandType getCommandType() {
		return commandType;
	}

	public void setCommandType(CommandType commandType) {
		this.commandType = commandType;
	}

	public ApplicationController getApplicationController() {
		return applicationController;
	}

	public void setApplicationController(
			ApplicationController applicationController) {
		this.applicationController = applicationController;
	}

	public ApplicationBuilder getApplicationBuilder() {
		return applicationBuilder;
	}

	public void setApplicationBuilder(ApplicationBuilder applicationBuilder) {
		this.applicationBuilder = applicationBuilder;
	}

	public PlatformNavigationService getNavi() {
		return navi;
	}

	public void setNavi(PlatformNavigationService navi) {
		this.navi = navi;
	}

	public IWindowSetViewBean getWinset() {
		return winset;
	}

	public void setWinset(IWindowSetViewBean winset) {
		this.winset = winset;
	}

	public MessageBundles getMessageBundles() {
		return messageBundles;
	}

	public void setMessageBundles(MessageBundles messageBundles) {
		this.messageBundles = messageBundles;
	}

}
